import Toast,{ToastType,Position,CloseFunction} from './Toast';
import {PlainObject,StringOrVue} from '../../../../types';
import {getUid} from '../../../util/common';
import {rootContainerVue,renders} from '../../js/app/rootContainer';
import 'animate.css';
//region 定义接口
/**
 * 传给api的选项
 * @property {StringOrVue} message				提示内容
 * @property {ToastType} [type]					轻提示类型
 * @property {number} [duration]				显示时长, 0表示不限制, type为'loading'时必为0
 * @property {Position} [position]				提示位置, 仅type为'normal'时有用
 * @property {boolean} [overlay]				显示遮罩层, type为'loading'时必为true
 * @property {boolean} [closeOnClick]			点击后关闭, type为'loading'时必为false
 * @property {boolean} [closeOnClickOverlay]	点击遮罩层后关闭, type为'loading'时必为false
 * @property {boolean} [max]					最大实例数, 0表示不限制, type为'loading'时不受影响
 * @property {boolean} [override]				替换最早的提示, 默认true, type为'loading'时不受影响
 */
export interface passOptions{
	message:StringOrVue,
	type?:ToastType,
	duration?:number,
	position?:Position,
	overlay?:boolean,
	closeOnClick?:boolean,
	closeOnClickOverlay?:boolean,
	contentClass?:string,
	contentStyle?:PlainObject,
	max?:number,
	override?:boolean,
}
/**
 * 传给Toast组件的选项
 */
export interface Options extends passOptions{
	uid:string,
	onClose?:CloseFunction,
	max:number,
}
/**
 * 返回值类型
 */
export type ResultType=Promise<void>&{close:() => void};
/**
 * 提示方法
 * @param {passOptions|string} opt 选项
 * @return {ResultType} 关闭后resolve的promise
 */
export interface AlertFunction{
	(opt:passOptions|string):ResultType
}
/**
 * 定义接口
 * @property {AlertFunction} show		不预定义类型的提示
 * @property {AlertFunction} normal		普通提示
 * @property {AlertFunction} loading	加载提示
 * @property {AlertFunction} success	成功提示
 * @property {AlertFunction} fail		错误提示
 */
export interface ToastApi{
	show:AlertFunction,
	normal:AlertFunction,
	loading:AlertFunction,
	success:AlertFunction,
	fail:AlertFunction,
}
//endregion

//加载中实例
let loadingContainer:Array<Options>=[];
//提示实例
const container:Array<Options>=[];
//渲染函数
renders.push(function(h){
	return h('div',{
		staticClass:'lexmis-ToastContainer',
	},loadingContainer.concat(container).map((opt) => {
		return h(Toast,{
			props:opt,
			key:opt.uid,
		});
	}));
});
rootContainerVue.$forceUpdate();
//标准化选项
function normalizedOptions(opt:passOptions|string,extend?:PlainObject):Options{
	if(typeof opt==='string'){
		opt={message:opt};
	}
	return Object.assign({
		uid:getUid(),
		max:1,
		override:true,
	},opt,extend);
}
//不预定义类型的提示
function realShow(option:Options):ResultType{
	const addOption=() => {
		const res:Promise<void>=new Promise((resolve) => {
			option.onClose=() => {
				const pos=container.indexOf(option);
				if(pos!==-1){
					container.splice(pos,1);
				}
				rootContainerVue.$forceUpdate();
				resolve();
			};
			container.unshift(option);
			rootContainerVue.$forceUpdate();
		});
		return Object.assign(res,{
			close:option.onClose!,
		});
	};
	if(option.type==='loading'){
		const res:Promise<void>=new Promise((resolve) => {
			option.onClose=() => {
				loadingContainer.length=0;
				rootContainerVue.$forceUpdate();
				resolve();
			};
			loadingContainer=[option];
			rootContainerVue.$forceUpdate();
		});
		return Object.assign(res,{
			close:option.onClose!,
		});
	}else if(option.max>=1&&container.length>=option.max){
		if(option.override){
			container.pop()!.onClose!();
			return addOption();
		}else{
			return Object.assign(
				Promise.reject(new Error(`轻提示达到最大个数${option.max}!`)),{
					close(){},
				}
			);
		}
	}else{
		return addOption();
	}
}
//不带预设类型的提示
function show(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt));
}
//普通提示
function normal(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'normal',
	}));
}
//加载提灯
function loading(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'loading',
	}));
}
//成功提示
function success(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'success',
	}));
}
//错误提示
function fail(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'fail',
	}));
}
const API:ToastApi={
	show,
	normal,
	loading,
	success,
	fail,
};
export default API;
export {rootContainerVue};
